package com.sharp.kernel.mybatis.repository;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sharp.kernel.constant.db.SqlConstant;
import com.sharp.kernel.constant.err.ErrCodeSys;
import com.sharp.kernel.mybatis.repository.inf.*;
import com.sharp.kernel.utils.DbUtil;
import com.sharp.kernel.utils.ReflectionUtil;
import com.sharp.kernel.validate.Validator;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.dao.DuplicateKeyException;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Title: BaseSqlRepository
 * Description: Copyright: Copyright (c) 2019 Company: BHFAE
 *
 * @author Sharp
 * @date 2022/6/7 14:38
 */
public class BaseSqlRepository<T, K extends Mapper<T>> extends BaseMybatisRepository<T, K> implements SqlSelectRepository<T>, SqlCountRepository<T>, SqlInsertRepository<T>, SqlUpdateRepository<T>, SqlDeleteRepository<T>, SqlInsertOrUpdateRepository<T> {

    @Override
    public int count(T entity) {
        return getDao().selectCount(entity);
    }

    @Override
    public int count(Example example) {
        return getDao().selectCountByExample(example);
    }

    @Override
    public boolean existedWithPrimaryKey(Object primaryKey) {
        return getDao().existsWithPrimaryKey(primaryKey);
    }

    @Override
    public boolean existed(Example example) {
        RowBounds rowBounds = new RowBounds(0, 1);
        return CollectionUtils.isNotEmpty(getDao().selectByExampleAndRowBounds(example, rowBounds));
    }

    @Override
    public int deleteByPrimaryKey(Object primaryKey) {
        return getDao().deleteByPrimaryKey(primaryKey);
    }

    @Override
    public int delete(T entity) {
        return getDao().delete(entity);
    }

    @Override
    public int delete(Example example) {
        return getDao().deleteByExample(example);
    }

    @Override
    public int disableByPrimaryKey(Object primaryKey) {
        T record = getDao().selectByPrimaryKey(primaryKey);
        return disable(record);
    }

    @Override
    public int disable(T entity) {
        Field validField = ReflectionUtil.getField(entity, SqlConstant.VALID_FIELD);
        Validator.assertNotNull(validField, ErrCodeSys.SYS_ERR_MSG, "不能软删除");
        ReflectionUtil.setValue(validField, entity, SqlConstant.INVALID);
        return getDao().updateByPrimaryKey(entity);
    }

    @Override
    public int disable(Example example) {
        List<T> recordList = getDao().selectByExample(example);
        int res = 0;
        for (T record : recordList) {
            res += disable(record);
        }
        return res;
    }

    @Override
    public List<T> select() {
        return getDao().selectAll();
    }

    @Override
    public PageInfo<T> select(int currentPage, int pageSize) {
        PageInfo<T> pageInfo = DbUtil.buildPageInfo(currentPage, pageSize, entityClass);
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(getDao().selectAll());
    }    @Override
    public int insert(Map<String, Object> entityMap) {
        T entity = DbUtil.buildEntity(entityMap, entityClass);
        DbUtil.setCreateAtTimeStamp(entity);
        DbUtil.setUpdateAtTimeStamp(entity);
        return getDao().insert(entity);
    }

    @Override
    public List<T> selectValid() {
        Example example = getExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SqlConstant.VALID_FIELD, SqlConstant.VALID);
        return getDao().selectByExample(example);
    }

    @Override
    public PageInfo<T> selectValid(int currentPage, int pageSize) {
        PageInfo<T> pageInfo = DbUtil.buildPageInfo(currentPage, pageSize, entityClass);
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(selectValid());
    }    @Override
    public int insert(List<T> entityList) {
        int result = 0;
        for (T entity : entityList) {
            result += insert(entity);
        }
        return result;
    }

    @Override
    public PageInfo<T> select(PageInfo<T> pageInfo) {
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(selectValid());
    }

    @Override
    public PageInfo<T> selectValid(PageInfo<T> pageInfo) {
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(selectValid());
    }    @Override
    public int insert(T entity) {
        DbUtil.setCreateAtTimeStamp(entity);
        DbUtil.setUpdateAtTimeStamp(entity);
        return getDao().insert(entity);
    }

    @Override
    public T selectByPrimaryKey(Object primaryKey) {
        return getDao().selectByPrimaryKey(primaryKey);
    }

    @Override
    public List<T> select(T entity) {
        return getDao().select(entity);
    }    @Override
    public int insertSelective(Map<String, Object> entityMap) {
        T entity = DbUtil.buildEntity(entityMap, entityClass);
        DbUtil.setCreateAtTimeStamp(entity);
        DbUtil.setUpdateAtTimeStamp(entity);
        return getDao().insertSelective(entity);
    }

    @Override
    public PageInfo<T> select(T entity, int currentPage, int pageSize) {
        PageInfo<T> pageInfo = DbUtil.buildPageInfo(currentPage, pageSize, entityClass);
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(getDao().select(entity));
    }

    @Override
    public PageInfo<T> select(T entity, PageInfo<T> pageInfo) {
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(getDao().select(entity));
    }    @Override
    public int insertSelective(List<T> entityList) {
        int result = 0;
        for (T entity : entityList) {
            result += insertSelective(entity);
        }
        return result;
    }

    @Override
    public List<T> select(T entity, RowBounds rowBounds) {
        return getDao().selectByRowBounds(entity, rowBounds);
    }

    @Override
    public List<T> select(Example example) {
        return getDao().selectByExample(example);
    }    @Override
    public int insertSelective(T entity) {
        DbUtil.setCreateAtTimeStamp(entity);
        DbUtil.setUpdateAtTimeStamp(entity);
        return getDao().insertSelective(entity);
    }

    @Override
    public PageInfo<T> select(Example example, int currentPage, int pageSize) {
        PageInfo<T> pageInfo = DbUtil.buildPageInfo(currentPage, pageSize, entityClass);
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(getDao().selectByExample(example));
    }

    @Override
    public PageInfo<T> select(Example example, PageInfo<T> pageInfo) {
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(getDao().selectByExample(example));
    }

    @Override
    public List<T> select(Example example, RowBounds rowBounds) {
        return getDao().selectByExampleAndRowBounds(example, rowBounds);
    }

    @Override
    public List<T> select(Map<String, Object> propertyMap) {
        Example example = getExample(propertyMap);
        return getDao().selectByExample(example);
    }

    @Override
    public PageInfo<T> select(Map<String, Object> propertyMap, int currentPage, int pageSize) {
        Example example = getExample(propertyMap);
        return select(example, currentPage, pageSize);
    }

    @Override
    public PageInfo<T> select(Map<String, Object> propertyMap, PageInfo<T> pageInfo) {
        Example example = getExample(propertyMap);
        PageHelper.startPage(pageInfo);
        return new PageInfo<>(getDao().selectByExample(example));
    }

    @Override
    public List<T> select(Map<String, Object> propertyMap, RowBounds rowBounds) {
        Example example = getExample(propertyMap);
        return getDao().selectByExampleAndRowBounds(example, rowBounds);
    }

    @Override
    public List<T> select(String propertyName, List<?> propertyList) {
        if (CollectionUtils.isEmpty(propertyList)) {
            return new ArrayList<>();
        }
        Example example = getExample(propertyName, propertyList);
        return getDao().selectByExample(example);
    }

    @Override
    public PageInfo<T> select(String propertyName, List<?> propertyList, int currentPage, int pageSize) {
        Example example = getExample(propertyName, propertyList);
        return select(example, currentPage, pageSize);
    }

    @Override
    public List<T> select(String propertyName, List<?> propertyList, RowBounds rowBounds) {
        Example example = getExample(propertyName, propertyList);
        return getDao().selectByExampleAndRowBounds(example, rowBounds);
    }

    @Override
    public T selectOne(T entity) {
        return getDao().selectOne(entity);
    }

    @Override
    public T selectOne(Example example) {
        return getDao().selectOneByExample(example);
    }

    @Override
    public T selectOne(Map<String, Object> propertyMap) {
        Example example = getExample(propertyMap);
        return getDao().selectOneByExample(example);
    }

    @Override
    public int insertOrUpdate(T entity, String... fieldNameArray) {
        try {
            return insert(entity);
        } catch (DuplicateKeyException e) {
            if (fieldNameArray != null && fieldNameArray.length != 0) {
                Example example = getExample(entity, fieldNameArray);
                return update(entity, example);
            } else {
                return updateByPrimaryKey(entity);
            }
        }
    }

    @Override
    public int insertOrUpdateSelective(T entity, String... fieldNameArray) {
        try {
            return insert(entity);
        } catch (DuplicateKeyException e) {
            if (fieldNameArray != null && fieldNameArray.length != 0) {
                Example example = getExample(entity, fieldNameArray);
                return updateSelective(entity, example);
            } else {
                return updateByPrimaryKeySelective(entity);
            }
        }
    }

    @Override
    public int updateByPrimaryKey(T entity) {
        return getDao().updateByPrimaryKey(entity);
    }

    @Override
    public int updateByPrimaryKeySelective(T entity) {
        return getDao().updateByPrimaryKeySelective(entity);
    }

    @Override
    public int update(T entity, Example example) {
        return getDao().updateByExampleSelective(entity, example);
    }

    @Override
    public int updateSelective(T entity, Example example) {
        return getDao().updateByExampleSelective(entity, example);
    }

    @Override
    public int update(T entity, String... fieldNameArray) {
        if (fieldNameArray.length != 0) {
            Example example = getExample(entity, fieldNameArray);
            return update(entity, example);
        } else {
            return updateByPrimaryKey(entity);
        }
    }

    @Override
    public int updateSelective(T entity, String... fieldNameArray) {
        if (fieldNameArray.length != 0) {
            Example example = getExample(entity, fieldNameArray);
            return updateSelective(entity, example);
        } else {
            return updateByPrimaryKeySelective(entity);
        }
    }

    @CacheEvict(keyGenerator = "cacheKeyByClass")
    public void refreshCache() {

    }















}
